package msrc

import (
	"context"
	"time"

	"gitlab.systems-fd.com/packages/golang/helpers/h"
)

// simpleService реализует интерфейс ServiceInterface для объединения его
// с SimpleService. Под капотом имплементирует функционал основного интерфейса.
type simpleService struct {
	service           SimpleService
	serviceCancelFunc *h.SyncValueStruct[context.CancelFunc]

	isStarted *h.SyncValueStruct[bool]
	isAlive   *h.SyncValueStruct[bool]

	graceStopPeriod time.Duration
}

// NewSimpleService реализует фабрику полноценного сервиса на основе переданного
// SimpleService. Вторым аргументом функция принимает не обязательный параметр
// graceStopPeriod, который отвечает за то, сколько времени (сек) необходимо ожидать
// правильного завершения сервиса. По умолчанию это значение - 5 сек.
// Если значение передано как 0 - время ожидания составит 1000 часов, что по сути
// будет означать ожидание полной, правильной остановки.
func NewSimpleService(service SimpleService, graceStopPeriod ...uint8) ServiceInterface {
	if 0 == len(graceStopPeriod) {
		graceStopPeriod = append(graceStopPeriod, 5)
	}

	gracePeriod := 1000 * time.Hour
	if graceStopPeriod[0] > 0 {
		gracePeriod = time.Duration(graceStopPeriod[0]) * time.Second
	}

	return &simpleService{
		service:           service,
		serviceCancelFunc: h.SyncValue[context.CancelFunc](func() {}),
		isStarted:         h.SyncValue[bool](false),
		isAlive:           h.SyncValue[bool](false),
		graceStopPeriod:   gracePeriod,
	}
}

// Run выполняет запуск сервера
func (s *simpleService) Run() error {
	s.isStarted.Set(true)

	s.isAlive.Set(true)
	defer s.isAlive.Set(false)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	s.serviceCancelFunc.Set(cancel)

	return s.service.Run(ctx)
}

// GracefulShutdown выполняет правильную остановку сервиса
func (s *simpleService) GracefulShutdown() {
	s.serviceCancelFunc.Get()()

	ctx, cancel := context.WithTimeout(context.Background(), s.graceStopPeriod)
	defer cancel()

	_ = h.EorSOne(s.service.GracefulShutdown)(s.graceStopPeriod)(ctx)
}

// IsStarted возвращает статус состояния запуска сервиса
func (s *simpleService) IsStarted() bool {
	return s.isStarted.Get()
}

// IsAlive возвращает статус сервиса: живой или нет
func (s *simpleService) IsAlive() bool {
	return s.isAlive.Get()
}
